package fun.qu_an.minecraft.gitfetch;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;

import java.io.FileNotFoundException;
import java.nio.file.NoSuchFileException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantLock;

import static net.minecraft.server.command.CommandManager.literal;

public class GitCommand {
	private static final ReentrantLock lock = new ReentrantLock();

	public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
		dispatcher.register(literal("git")
			.requires(source -> source.hasPermissionLevel(4))
			.then(literal("reload")
				.executes(GitCommand::executeReload))
			.then(literal("fetch")
				.executes(GitCommand::executeFetch)));
	}

	private static int executeFetch(CommandContext<ServerCommandSource> context) {
		ServerCommandSource source = context.getSource();
		if (lock.isLocked()) {
			source.sendMessage(Text.of("有一个同步任务未完成"));
			return 0;
		}
		CompletableFuture.runAsync(() -> {
			try {
				if (!lock.tryLock()) {
					source.sendMessage(Text.of("有一个同步任务未完成"));
					return;
				}
				Git git = GitFetchConfig.getInstance().getGit();
				if (git == null) {
					try {
						GitFetchConfig.reload(source.getServer());
					} catch (RepositoryNotFoundException e) {
						source.sendMessage(Text.of("未找到仓库！" + e.getMessage()));
						return;
					} catch (FileNotFoundException | NoSuchFileException e) {
						source.sendMessage(Text.of("文件/路径不存在 " + e.getMessage()));
						return;
					} catch (Exception e) {
						source.sendMessage(Text.of("获取仓库时出现意外错误 " + e.getMessage()));
						return;
					}
					git = GitFetchConfig.getInstance().getGit();
					if (git == null) {
						source.sendMessage(Text.of("未找到仓库！"));
						return;
					}
				}
				source.sendMessage(Text.of("开始同步..."));
				try {
					git.stashCreate().call();
					git.reset().setMode(ResetCommand.ResetType.HARD).call();
					source.sendMessage(Text.of("放弃所有本地更改..."));
					git.fetch()
						.setRemote("origin")
						.setTimeout(60)
						.call();
					source.sendMessage(Text.of("同步成功！"));
				} catch (InvalidRemoteException e) {
					source.sendMessage(Text.of("无效的远程仓库 " + e.getMessage()));
				} catch (GitAPIException e0) {
					source.sendMessage(Text.of("需要登陆，正在重试..."));
					GitFetchConfig.GitFetchJsonConfig jsonConfig = GitFetchConfig.getInstance().getJsonConfig();
					try {
						git.fetch()
							.setRemote("origin")
							.setTimeout(60)
							.setCredentialsProvider(new UsernamePasswordCredentialsProvider(jsonConfig.getUsername(), jsonConfig.getPassword()))
							.call();
						source.sendMessage(Text.of("同步成功！"));
					} catch (InvalidRemoteException e) {
						source.sendMessage(Text.of("无效的远程仓库 " + e.getMessage()));
					} catch (GitAPIException e) {
						source.sendMessage(Text.of("同步时出现意外错误 " + e.getMessage()));
					}
				}
			} finally {
				lock.unlock();
			}
		}, Util.getDownloadWorkerExecutor());
		return 1;
	}

	private static int executeReload(CommandContext<ServerCommandSource> context) {
		ServerCommandSource source = context.getSource();
		try {
			GitFetchConfig.reload(source.getServer());
			source.sendMessage(Text.of("重载成功！"));
			return 1;
		} catch (RepositoryNotFoundException e) {
			source.sendMessage(Text.of("未找到仓库！" + e.getMessage()));
			return 0;
		} catch (FileNotFoundException | NoSuchFileException e) {
			source.sendMessage(Text.of("文件/路径不存在 " + e.getMessage()));
			return 0;
		} catch (Exception e) {
			source.sendMessage(Text.of("重载配置文件时出现意外错误 " + e.getMessage()));
			return 0;
		}
	}
}
